package rpc.netty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import rpc.common.MyInvocation;
import rpc.netty.coder.MyMessageToByteEncoder;
import rpc.netty.coder.MyReplayingDecoder;

/**
 * 自定义Netty客户端
 */
public class MyNettyClient {
    private static MyClientHandler myClientHandler;

    /**
     * 发送请求
     */
    public static String send(String hostname, Integer port, MyInvocation myInvocation) {
        //构建线程池
        try (NioEventLoopGroup group = new NioEventLoopGroup()) {
            //构建客户端启动对象
            Bootstrap bootstrap = new Bootstrap();
            //设置线程池
            bootstrap.group(group);
            //设置通道
            bootstrap.channel(NioSocketChannel.class);
            //设置即时传输
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            //设置处理器
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                /**
                 * 通道初始化
                 */
                @Override
                protected void initChannel(SocketChannel socketChannel) {
                    //获取管道
                    ChannelPipeline channelPipeline = socketChannel.pipeline();
                    //添加解码器
                    channelPipeline.addLast(new MyReplayingDecoder());
                    //添加编码器
                    channelPipeline.addLast(new MyMessageToByteEncoder());
                    myClientHandler = new MyClientHandler();
                    myClientHandler.setMyInvocation(myInvocation);
                    //添加处理器
                    channelPipeline.addLast(myClientHandler);
                }
            });
            //构建客户端连接，同步阻塞，等待操作完成
            ChannelFuture channelFuture = bootstrap.connect(hostname, port).sync();
            //监听关闭通道，同步阻塞，等待操作完成
            channelFuture.channel().closeFuture().sync();
            //添加监听器
            channelFuture.addListener(new ChannelFutureListener() {
                /**
                 * 操作完成
                 */
                @Override
                public void operationComplete(ChannelFuture channelFuture) {
                    System.out.println("调用结束");
                }
            });
            return myClientHandler.getResult();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
